// let _Vue = null
// class Store{
//   constructor(options){
//     const {
//       state = {},
//       getters = {},
//       mutations = {},
//       actions = {}
//     } = options
//     this.state = _Vue.observable(state)
//     this.getters = Object.create(null)
//     Object.keys(getters).forEach(key => {
//       Object.defineProperty(this.getters,key,{
//         get:()=>getters[key](state)
//       })
//     })
//     this._mutations = mutations
//     this._actions = actions
//   }
//   commit(type,payload){
//     this._mutations[type](this.state,payload)
//   }
//   dispatch(type,payload){
//     this._actions[type](this,payload)
//   }
// }
// function install(Vue){
//   _Vue = Vue
//   _Vue.mixin({
//     beforeCreate(){
//       if(this.$options.store){
//         _Vue.prototype.$store = this.$options.store // 原型注册
//       }
//     }
//   })
// }
// export default {
//   Store,
//   install
// }

// 将install中传入的vue实例保存到外部
let _Vue = null

// 声明vuex中的Store类
class Store {
  constructor (options) {
    const {
      state = {},
      getters = {},
      mutations = {},
      actions = {}
    } = options
    // 将传入的state变成响应式并且在Store的实例上也储存一份this.state，
    this.state = _Vue.observable(state)
    // 创建一个没有原型的getters备用
    this.getters = Object.create(null)
    // 将传入的getters的属性名赋值给this.getters，并且get赋值为传入的方法
    Object.keys(getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => getters[key](state)
      })
    })
    // 保存备份
    this._mutations = mutations
    this._actions = actions
  }
  // commit方法调用保存的备份_mutations
  commit (type, payload) {
    this._mutations[type](this.state, payload)
  }
  //  和类似_mutations
  dispatch (type, payload) {
    this._actions[type](this, payload)
  }
}

function install (Vue) {
  _Vue = Vue
  // 和vueRouter一样，使用mixin全局混入 $store，并且有一个if判断，只有在根实例上才会添加，不会重复
  _Vue.mixin({
    beforeCreate () {
      if (this.$options.store) {
        _Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default {
  Store,
  install
}
